#pragma once
#if !defined(_EdgeSet_)
#define _EdgeSet_

#include <set>
#include <map>
#include <src/miscellaneous/OS_basic.h>
#include <src/data/ParticleSet.h>
#include <src/miscellaneous/pattern/Observable.h>
/*
	Weight_Set_base is the base class defining connectivity between a set of element \{S_i\}_{i=1,..,N}.
	It must provides basically the functionality of a weighted graph, that is a container of kind
	std::map<std::pair<indice_type, indice_type>, weight_type>.

template <class indice_type = OS_size, class weight_type = OS_double>
class weight_set_base :
public std::map< std::pair<indice_type, indice_type>, weight_type> 
{
public : 
	typedef typename indice_type			indice_type;
	typedef typename std::pair<indice_type, indice_type> edge_type;
	typedef typename weight_type weight_type;
	typedef std::map< std::pair<indice_type, indice_type>, weight_type>  container_type;

	virtual OS_size cardinal (const indice_type& i) const = 0;
};

	For multidimensional particle method, the connectivity between particles is computed during the calculus.
	This connectivity is based on a variable of state (usually the solution after each iteration).
	This is the reason why we embed a design pattern of Observable / Observer : the connectivity Observe a variable
	and update itself after a change of this Observable.

template <class ParticleList, class Weight = OS_double>
class weight_set_traits :
	public OS::Observer
	,public state_variable_traits<smart_ptr< OS::Observable_helper<ParticleList>>>,
	public weight_set_base<typename ParticleList::indice_type, Weight>
{
public :
	typedef typename ParticleList							particles_list_type;
	typedef typename particles_list::particle_type			particle_type;
	typedef state_variable_traits<smart_ptr< OS::Observable_helper<ParticleList>>> state_variable_traits_type;

	typedef typename Weight												weight_type;


	weight_set_traits( ) {} ;
	weight_set_traits( const state_variable_type& S) : state_variable_traits_type(S) {
			if (get_state_variable() ) {
				registerWith( get_state_variable() );
			}
	};

	virtual void set_state_variable(const state_variable_type& S)
	{
		if (get_state_variable() != S) {
			if (get_state_variable() )
				unregisterWith(get_state_variable() );
			state_variable_ = S;
			if (get_state_variable() ) {
				registerWith( get_state_variable() );
			}
		}
	};
	virtual OS_size cardinal (const indice_type& i) const = 0;


protected :
	virtual void update() = 0; //compute weights
};
	This is a base class for
	multi dimensional particle connectivity computations.
template <class ParticleList, class Weight = OS_double>
class weight_set_particle : public weight_set_traits<ParticleList, Weight>
{
public :
	typedef typename	std::vector<indice_type>				cardinal_map_type;
	typedef typename	weight_set_traits<ParticleList, Weight>		Base;
	typedef typename 	container_type::iterator iterator;
	weight_set_particle( ) {};
	weight_set_particle( const state_variable_type& S) : Base(S)
	{};


	virtual OS_size cardinal (const indice_type& i) const {
		return cardinal_[i];
	};
protected :
	cardinal_map_type cardinal_;
};

	For the one dimensional case, connectivity between particles is fully deduced by increasing rearangement.

template <>
class weight_set_particle<particle, OS_double > 
	: public weight_set_traits<particle, OS_double>
	{
public :
	typedef  weight_set_traits<particle, OS_double>		Base;
	weight_set_particle( ) {};
	weight_set_particle( const state_variable_type& S) : Base(S)
	{};
	void update() {std::sort(get_state_variable()->begin(),get_state_variable()->end());};
	virtual OS_size cardinal (const indice_type& i) const {
		if (i>1 && i < get_state_variable()->size()) return 2;
		return 1;
	};

};

*/


#endif // _EdgeSet_
